package juc;
/*
线程交替输出问题解决方法2
使用线程通信，使用notify和wait方法

这种方式有两个问题：

问题1：启动时不一定是t1先获得锁，可能会先打印字母。如何保证t1先获得锁呢？ 使用CountDownLatch。
问题2：这个线程会停止吗？ 不会，最终等待队列中一定有一个线程存在。
 */
import java.util.concurrent.locks.LockSupport;
/**
 * Description:
 *      两个线程交替输出
 *                 第一个线程：1 2 3 4 5 6 7
 *                 第二个线程： A B C D E F G
 *        输出结果：1A2B3C4D5E6F7G
 */
public class Test05 {

    public static void main(String[] args){
        char[] nums = "1234567".toCharArray();
        char[] chars = "ABCDEFG".toCharArray();

        Object lock = new Object();

        /**
         * synchronized的原理，多个线程同时抢一把锁，该锁维护一个队列（同步队列），没有争抢到锁的所有线程在同一个同步队列里。
         * wait:该线程释放锁后阻塞，该线程进入另一个队列（等待队列）
         * notify:随机叫醒等待队列中的任何一个线程
         * notifyAll: 唤醒等待队列中的所有线程，让他们去争夺同一把锁，谁争抢到谁执行。
         *
         * 下面t1和t2同时争抢同一把锁：
         *  1.假如t1争抢到锁，则t1执行而t2进入到该锁的同步队列中，
         *  2.t1执行时，执行到notify，这时等待队列中没有线程，继续执行到wait时，释放锁并让t1进入到等待队列，等待notify唤醒
         *  3.由于t1释放锁了，同步队列中的t2就可以获得锁执行，执行到notify时，会随机唤醒等待队列中的一个线程，因为队列中只有一个t1,所以t1去争抢锁；t2执行到wait,t2释放锁并让t2进入到等待队列，等待notify唤醒,t1会获得锁执行。
         *  4.依次循环
         */

        Thread t1 = new Thread(()->{
            try{
                synchronized (lock){
                    for(char temp: nums){
                        System.out.println(temp);
                        lock.notify();
                        lock.wait();
                    }
                }
            }catch (Exception e){

            }
        },"t1");

        Thread t2 = new Thread(()->{
            try{

                synchronized (lock){
                    for(char temp: chars){

                        System.out.println(temp);
                        lock.notify();
                        lock.wait();
                    }
                }

            }catch (Exception e){

            }
        },"t2");

        t1.start();
        t2.start();
    }
}

